package security.service;

import framework.config.SecurityConfig;
import framework.security.token.AuthTokenInfo;
import lombok.Getter;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;

import java.util.Date;
import java.util.Random;

public class AuthTokenGeneratorDefault implements AuthTokenGenerator {

    @Getter
    private String cacheName = "global";

    private final CacheManager cacheManager;


    public AuthTokenGeneratorDefault(SecurityConfig securityConfig, CacheManager cacheManager) {
        this.cacheManager = cacheManager;
        if (this.cacheManager == null)
            throw new RuntimeException("Cache module not enable");
    }

    @Override
    public long newSid(long id) {
        return Math.abs(new Random().nextLong()) % 9007199254740991L;
    }

    @Override
    public AuthTokenInfo newToken(long id, int duration, long sid) {
        Date expireDate = new Date(new Date().getTime() + duration * 1000L);
        return new AuthTokenInfo(id, expireDate, duration, sid);
    }

    @Override
    public AuthTokenInfo updateToken(AuthTokenInfo tokenInfo) {
        Cache cache = cacheManager.getCache(getCacheName());
        if (cache == null) {
            throw new RuntimeException("Please config default settings in ehcache.xml");
        }

        //
        String cacheKey = "AuthTokenGenerator_" + tokenInfo.getId() + "_" + tokenInfo.getSid();

        // 验证上一更新, 上次生成的token，使用时间不超过1分钟则不重新生成
        AuthTokenInfo info = cache.get(cacheKey, AuthTokenInfo.class);
        if (info != null) {
            //
            if (!isAllowUpdate(info)) {
                return info;
            }
        }

        Date expired = new Date(new Date().getTime() + tokenInfo.getDuration() * 1000L);
        // 为会话生成新的token
        AuthTokenInfo newInfo = new AuthTokenInfo(tokenInfo.getId(), expired, tokenInfo.getDuration(), tokenInfo.getSid());
        cache.put(cacheKey, newInfo);
        return newInfo;
    }

    /**
     * 是否需要更新,使用时间不超过1分钟则不重新生成
     *
     * @param info
     * @return
     */
    protected boolean isAllowUpdate(AuthTokenInfo info) {
        long threshold = 60;
        if (info.getDuration() < threshold) {
            // 有效期小于阀值，允许更新
            return true;
        }
        long createTime = info.getExpireTime().getTime() - (info.getDuration() * 1000L);
        return new Date().getTime() - createTime > (threshold * 1000L);
    }
}
